package config

import (
	"context"
	"encoding/json"
	"log"
	"sync"
	"time"

	"github.com/go-redis/redis/v8"
)

// DynamicConfig 动态配置
type DynamicConfig struct {
	client        *redis.Client
	configs       map[string]interface{}
	configsMutex  sync.RWMutex
	listeners     map[string][]ConfigChangeListener
	listenerMutex sync.RWMutex
	stopChan      chan struct{}
}

// ConfigChangeListener 配置变更监听器
type ConfigChangeListener func(key string, oldValue, newValue interface{})

// NewDynamicConfig 创建动态配置中心
func NewDynamicConfig(client *redis.Client) *DynamicConfig {
	return &DynamicConfig{
		client:    client,
		configs:   make(map[string]interface{}),
		listeners: make(map[string][]ConfigChangeListener),
		stopChan:  make(chan struct{}),
	}
}

// Start 启动配置中心
func (d *DynamicConfig) Start(ctx context.Context) {
	// 初始加载所有配置
	d.loadAllConfigs(ctx)

	// 启动配置监听
	go d.watchConfigChanges(ctx)
}

// Stop 停止配置中心
func (d *DynamicConfig) Stop() {
	close(d.stopChan)
}

// GetString 获取字符串配置
func (d *DynamicConfig) GetString(key string, defaultValue string) string {
	d.configsMutex.RLock()
	defer d.configsMutex.RUnlock()

	if value, ok := d.configs[key]; ok {
		if strValue, ok := value.(string); ok {
			return strValue
		}
	}
	return defaultValue
}

// GetInt 获取整数配置
func (d *DynamicConfig) GetInt(key string, defaultValue int) int {
	d.configsMutex.RLock()
	defer d.configsMutex.RUnlock()

	if value, ok := d.configs[key]; ok {
		if floatValue, ok := value.(float64); ok {
			return int(floatValue)
		}
		if intValue, ok := value.(int); ok {
			return intValue
		}
	}
	return defaultValue
}

// GetFloat 获取浮点数配置
func (d *DynamicConfig) GetFloat(key string, defaultValue float64) float64 {
	d.configsMutex.RLock()
	defer d.configsMutex.RUnlock()

	if value, ok := d.configs[key]; ok {
		if floatValue, ok := value.(float64); ok {
			return floatValue
		}
	}
	return defaultValue
}

// GetBool 获取布尔配置
func (d *DynamicConfig) GetBool(key string, defaultValue bool) bool {
	d.configsMutex.RLock()
	defer d.configsMutex.RUnlock()

	if value, ok := d.configs[key]; ok {
		if boolValue, ok := value.(bool); ok {
			return boolValue
		}
	}
	return defaultValue
}

// GetDuration 获取时间配置
func (d *DynamicConfig) GetDuration(key string, defaultValue time.Duration) time.Duration {
	strValue := d.GetString(key, "")
	if strValue == "" {
		return defaultValue
	}

	duration, err := time.ParseDuration(strValue)
	if err != nil {
		return defaultValue
	}
	return duration
}

// GetObject 获取对象配置
func (d *DynamicConfig) GetObject(key string, result interface{}) error {
	d.configsMutex.RLock()
	value, ok := d.configs[key]
	d.configsMutex.RUnlock()

	if !ok {
		return nil
	}

	// 如果是字符串，尝试解析JSON
	if strValue, ok := value.(string); ok {
		return json.Unmarshal([]byte(strValue), result)
	}

	// 否则尝试将整个对象转为目标类型
	jsonBytes, err := json.Marshal(value)
	if err != nil {
		return err
	}
	return json.Unmarshal(jsonBytes, result)
}

// AddListener 添加配置变更监听器
func (d *DynamicConfig) AddListener(key string, listener ConfigChangeListener) {
	d.listenerMutex.Lock()
	defer d.listenerMutex.Unlock()

	if _, ok := d.listeners[key]; !ok {
		d.listeners[key] = make([]ConfigChangeListener, 0)
	}
	d.listeners[key] = append(d.listeners[key], listener)
}

// loadAllConfigs 加载所有配置
func (d *DynamicConfig) loadAllConfigs(ctx context.Context) {
	// 配置键的前缀
	const configPrefix = "config:"

	// 使用SCAN命令查找所有配置键
	iter := d.client.Scan(ctx, 0, configPrefix+"*", 100).Iterator()
	for iter.Next(ctx) {
		key := iter.Val()
		shortKey := key[len(configPrefix):]

		// 获取配置值
		value, err := d.client.Get(ctx, key).Result()
		if err != nil {
			log.Printf("加载配置失败: %s, 错误: %v", key, err)
			continue
		}

		// 解析配置值（JSON格式）
		var parsedValue interface{}
		if err := json.Unmarshal([]byte(value), &parsedValue); err != nil {
			log.Printf("解析配置失败: %s, 错误: %v", key, err)
			continue
		}

		// 更新配置
		d.updateConfig(shortKey, parsedValue)
	}
	if err := iter.Err(); err != nil {
		log.Printf("扫描配置失败: %v", err)
	}
}

// watchConfigChanges 监听配置变更
func (d *DynamicConfig) watchConfigChanges(ctx context.Context) {
	// 订阅配置变更通知
	pubsub := d.client.Subscribe(ctx, "config:changes")
	defer pubsub.Close()

	// 接收消息
	ch := pubsub.Channel()

	for {
		select {
		case <-d.stopChan:
			return
		case msg := <-ch:
			// 解析变更通知
			var change struct {
				Key string `json:"key"`
			}
			if err := json.Unmarshal([]byte(msg.Payload), &change); err != nil {
				log.Printf("解析配置变更通知失败: %v", err)
				continue
			}

			// 获取最新配置
			key := "config:" + change.Key
			value, err := d.client.Get(ctx, key).Result()
			if err != nil {
				log.Printf("获取配置失败: %s, 错误: %v", key, err)
				continue
			}

			// 解析配置值
			var parsedValue interface{}
			if err := json.Unmarshal([]byte(value), &parsedValue); err != nil {
				log.Printf("解析配置失败: %s, 错误: %v", key, err)
				continue
			}

			// 更新配置
			d.updateConfig(change.Key, parsedValue)
		}
	}
}

// updateConfig 更新配置并通知监听器
func (d *DynamicConfig) updateConfig(key string, newValue interface{}) {
	d.configsMutex.Lock()
	oldValue, _ := d.configs[key]
	d.configs[key] = newValue
	d.configsMutex.Unlock()

	// 通知监听器
	d.notifyListeners(key, oldValue, newValue)
}

// notifyListeners 通知监听器配置变更
func (d *DynamicConfig) notifyListeners(key string, oldValue, newValue interface{}) {
	d.listenerMutex.RLock()
	listeners, ok := d.listeners[key]
	d.listenerMutex.RUnlock()

	if ok {
		for _, listener := range listeners {
			go listener(key, oldValue, newValue)
		}
	}

	// 通知通配符监听器
	d.listenerMutex.RLock()
	wildcardListeners, ok := d.listeners["*"]
	d.listenerMutex.RUnlock()

	if ok {
		for _, listener := range wildcardListeners {
			go listener(key, oldValue, newValue)
		}
	}
}
